package com.thinkit.processor.channel;

import cn.hutool.core.io.FileUtil;
import com.thinkit.core.base.BaseContextKit;
import com.thinkit.core.constant.Channel;
import com.thinkit.directive.components.AbstractNotify;
import com.thinkit.directive.components.DirectiveInterceptor;
import com.thinkit.directive.components.NotifyComponent;
import com.thinkit.directive.components.TemplateComponent;
import com.thinkit.processor.license.LicenseProperties;
import com.thinkit.utils.model.ApiResult;
import com.thinkit.utils.properties.ThinkItProperties;
import com.thinkit.utils.utils.Checker;
import freemarker.template.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Slf4j
public abstract class BaseChannelAdaptService implements BaseChannelService{

    protected String tempPath;

    protected String destPath;

    @Autowired
    protected TemplateComponent templateComponent;

    @Autowired
    protected  DirectiveInterceptor interceptor;

    @Autowired
    protected ThinkItProperties thinkItProperties;

    @Autowired
    protected LicenseProperties licenseProperties;

    @Autowired
    protected NotifyComponent notifyComponent;

    @Autowired
    SimpMessagingTemplate SMT;

    public void notifyIt(String id){};

    public void notifyIt(String id,Boolean notify){};

    public void notifyIt(){};

    public void notifyIt(Boolean notify){};

    public void notifyIt(Map<String,Object> params){};

    public void notifyIt(List params){};

    public void notifyIt(Map<String,Object> params,Boolean notify){};

    public ApiResult execuate(){
        try {
            return doIt(null);
        } catch (Exception e){
            log.error("++++++++++系统出现异常请排查+++++++++++++++++++++++");
            log.error(e.getMessage());
            throw e;
        }

    }

    public ApiResult execuate(Map<String,Object> variable){
        try {
            return doIt(variable);
        } catch (Exception e){
            log.error("++++++++++系统出现异常请排查+++++++++++++++++++++++");
            log.error(e.getMessage());
            throw e;
        }
    }

    private ApiResult doIt(Map<String,Object> variable){
        BaseContextKit.setSiteId(getSiteId());
        BaseContextKit.setUserId(getUserId());
        Map<String,Object> params = loadTempParams(variable);
        if(params!=null){
            params.put(Channel.CHANNER_NAME,getName().getName());
            Configuration configuration=interceptor.injecShareVariable(variable);
            if(!validDomain(configuration.getSharedVariable(Channel.DOMAIN).toString(),
                configuration.getSharedVariable("dt").toString())){
                return ApiResult.result(5037);
            }
            String destPath = loadDestPath();
            if(continueNotify(tempPath,destPath)){
                return templateComponent.createStaticFile(format(tempPath),format(destPath),params,configuration);
            }
        }
        return ApiResult.result(5024);
    }

    public ApiResult execuate(AbstractNotify abstractNotify){
        ApiResult apiResult = execuate();
        abstractNotify.notifyMsg(getUserId(),apiResult);
        return apiResult;
    }

    public void execuate(boolean afterCall){
        ApiResult apiResult =null;
        try {
             apiResult=execuate();
        }catch (Exception e){
            throw  e;
        }finally {
            if(afterCall){
                callBack(apiResult);
            }
        }
    }

    public void execuate(boolean afterCall,boolean notify){
        ApiResult apiResult =null;
        try {
            apiResult=execuate();
        }finally {
            if(notify){
                notifyComponent.notifyMsg(getUserId(),apiResult);
            }
            if(afterCall){
                callBack(apiResult);
            }
        }
    }


    public void execuate(boolean afterCall,String ... variableName){
        ApiResult apiResult =null;
        try {
            apiResult=execuate();
        }finally {
            if(afterCall){
                callBack(apiResult);
            }
        }
    }

    public void execuate(AbstractNotify notify,boolean callBack){
        ApiResult apiResult= execuate();
        notify.notifyMsg(getUserId(),apiResult);
        if(callBack){
            callBack(apiResult);
        }
    }

    public void execuate(boolean afterCall,boolean notify,Map<String,Object> variable){
        ApiResult apiResult =null;
        try {
            apiResult=execuate(variable);
        }finally {
            if(notify){
                notifyComponent.notifyMsg(getUserId(),apiResult);
            }
            if(afterCall){
                callBack(apiResult);
            }
        }
    }

    public void callBack(Object param){

    }


    private boolean continueNotify(String tempPath,String destPath){
        String finalTempPath = thinkItProperties.getTemplate()+tempPath;
        return Checker.BeNotBlank(tempPath) && Checker.BeNotBlank(destPath) && FileUtil.exist(finalTempPath);
    }

    private String format(String path){
        if(Checker.BeNotBlank(path)){
            return path.replace("\\","/");
        }
        return null;
    }

    private boolean validDomain(String domain,String dt){
        if(Checker.BeNotBlank(domain) || Checker.BeNotBlank(dt)){
            if(licenseProperties.needVerifyDomain()){
                List<String> domains = Arrays.asList(licenseProperties.getDomain().split("\\|"));
                if(Checker.BeNotBlank(domain)){
                    domain = domain.replace("http://","").replace("https://","");
                    if(!domains.contains(domain)){
                        return false;
                    }
                }
                if(Checker.BeNotBlank(dt)){
                    boolean hasDomain = false;
                    dt = dt.replace("http://","").replace("https://","");
                    for(String d:domains){
                        if(dt.contains(d)){
                            hasDomain = true;
                        }
                    }
                    if(!hasDomain){
                        return false;
                    }
                }
            }
        }
        return true;
    }

    // load temp path for gen
    protected abstract String loadTempPath();

    // load location path  for gen
    protected abstract String loadDestPath();


    protected abstract Map<String,Object> loadTempParams(Map<String,Object> variable);

    protected void setPath(Map<String,Object> params){
        if(Checker.BeNotNull(params) && !params.isEmpty()){
            boolean hasTemp=params.containsKey(Channel.TEMP_PATH) && Checker.BeNotNull(params.get(Channel.TEMP_PATH));
            boolean hasDest=params.containsKey(Channel.DEST_PATH) && Checker.BeNotNull(params.get(Channel.DEST_PATH));
            if(hasTemp){
                this.tempPath =params.get(Channel.TEMP_PATH).toString();
            }
            if(hasDest){
                this.destPath = params.get(Channel.DEST_PATH).toString().replace("\\","/");
            }
        }
    }

    protected void setPath(Map<String,Object> params,Boolean absoutePath){
        if(!absoutePath){
            if(Checker.BeNotNull(params) && !params.isEmpty()){
                boolean hasDest=params.containsKey(Channel.DEST_PATH) && Checker.BeNotNull(params.get(Channel.DEST_PATH));
                if(hasDest){
                    String destPath = params.get(Channel.DEST_PATH).toString();
                    if(! destPath.contains(thinkItProperties.getSitePath())){
                        String finalDestPath = thinkItProperties.getSitePath()+params.get(Channel.DEST_PATH).toString();
                        params.put(Channel.DEST_PATH,finalDestPath.replace("\\","/"));
                    }
                }
            }
        }
        setPath(params);
    }

    protected String getSiteId(){
        Object siteId = ChannelThreadLocal.get(Channel.SITE_ID);
        if(Checker.BeNotNull(siteId)){
            return siteId.toString();
        }
        return null;
    }

    protected String getUserId(){
        Object userId = ChannelThreadLocal.get(Channel.USER_ID);
        if(Checker.BeNotNull(userId)){
            return userId.toString();
        }
        return null;
    }

    @Override
    public BaseChannelService clone(boolean singleton) throws CloneNotSupportedException {
        if(singleton){
            return this;
        }
        return (BaseChannelService) super.clone();
    }
}
